package com.project.web.controller.user;

import com.alipay.api.AlipayApiException;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.project.common.config.AlipayConfig;
import com.project.common.utils.TimeUuidUtil;
import com.project.user.domain.UserOrder;
import com.project.user.domain.UserOrderDetail;
import com.project.user.service.IUserOrderService;
import com.project.web.controller.common.BaseController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;

@Controller
@RequestMapping("/AlipayController")
public class AlipayController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(AlipayController.class);

    @Autowired
    private IUserOrderService userOrderService;

    DefaultAlipayClient alipayClient = new DefaultAlipayClient(
            AlipayConfig.gatewayUrl, AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.sign_type);

    /**
     * 支付
     *
     * @param userOrder
     * @param goodsId
     * @param goodsPrice
     * @param goodsNum
     * @param isFromCart
     * @param goodsName
     * @param response
     * @throws IOException
     */
    @PostMapping("/PayPage")
    public void payController(UserOrder userOrder, Long[] goodsId, Double[] goodsPrice, Integer[] goodsNum, Integer isFromCart, String[] goodsName, HttpServletResponse response) throws IOException, AlipayApiException {
        //生成订单详情
        List<UserOrderDetail> details = new ArrayList<>();
        for (int i = 0; i < goodsId.length; i++) {
            UserOrderDetail detail = new UserOrderDetail(0L, goodsId[i], goodsNum[i]);
            detail.setGoodsPrice(goodsPrice[i]);
            details.add(detail);
        }
        userOrder.setUserId(this.getUserId());
        userOrder.setStatus(4);
        userOrder.setDetails(details);
        //生成订单
        String orderIds = userOrderService.insertUserOrder(userOrder, isFromCart, this.getUser().getIsvip());

        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        /** 同步通知，支付完成后，支付成功页面*/
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        /** 异步通知，支付完成后，需要进行的异步处理*/
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        //商户订单号
        String out_trade_no = orderIds.substring(1);
        //付款金额
        double payAmount = userOrder.getTotalPrice();
        //菜品名
        String goodsNames = goodsName[0];
        for (int i = 1; i < goodsName.length; i++) {
            goodsNames = goodsNames + "," + goodsName[i];
        }
        //实物
        String subject = "外卖人订餐：" + goodsNames;
        alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                + "\"total_amount\":\"" + payAmount + "\","
                + "\"subject\":\"" + subject + "\","
                + "\"timeout_express\":\"10m\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        //请求
        String form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单

        log.info(form);
        response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
        response.getWriter().write(form);//直接将完整的表单html输出到页面
        response.getWriter().flush();
        response.getWriter().close();
    }

    /**
     * 获取支付宝POST过来反馈信息
     *
     * @param params
     * @param requestParams
     * @throws Exception
     * @return{gmt_create=2019-12-24 18:01:25, charset=utf-8, gmt_payment=2019-12-24 18:01:35, notify_time=2019-12-24 18:01:36, subject=2, sign=SgNs7HaYO5Kl7gSZ6wGgI96nO1k32+f6SnCDfDRZx8/osBr0Mc8+ZjyEvOyKNQI4ieECcQtu7vqqiHfd6jwA0JN5G3FYKH9Oh8dNuX8VSDRyXxDPn7sT3G4SA81kfF6/R/CezqDNihLya6Sa3WjZ9PPtTBeFVUnJp7Lv6BVo5aK+pb02u2WhY9wQUT7jYrMRbF3/1z8onUoZYulL3q2qwalSN27yVkXxU3K02pVdkr9sG8cN7/Y2BRxmcTE3QiG9jY1Yi8zIOzoK/ajDzhPrwDdoUzMLx3pUcBFUvdibHTt9mm3Ut4yjD1w5flsAAYKIgq0msUCI/GcXulX30M7b9A==, buyer_id=2088102180013990, invoice_amount=300.00, version=1.0, notify_id=2019122400222180135013991000651753, fund_bill_list=[{"amount":"300.00","fundChannel":"ALIPAYACCOUNT"}], notify_type=trade_status_sync, out_trade_no=178, total_amount=300.00, trade_status=TRADE_SUCCESS, trade_no=2019122422001413991000161161, auth_app_id=2016101600702841, receipt_amount=300.00, point_amount=0.00, app_id=2016101600702841, buyer_pay_amount=300.00, sign_type=RSA2, seller_id=2088102179889744}
     */
    public Map<String, String> getAlipayPost(Map<String, String> params, Map<String, String[]> requestParams) throws UnsupportedEncodingException {
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        return params;
    }

    /**
     * 功能：支付宝服务器异步通知页面
     * 如果没有收到该页面返回的 success  支付宝会一直发送请求 一共分不同时间段 发送八次
     *
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping("/notifyUrl")
    @ResponseBody
    public String alipayNotify(HttpServletRequest request) throws Exception {
        log.info("支付成功, 进入同步通知接口...");

        //获取支付宝POST过来反馈信息 获取params来进行验签
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        params = getAlipayPost(params, requestParams);
        log.info("params=====================================" + params);

        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.sign_type); //调用SDK验证签名

        /** 实际验证过程建议商户务必添加以下校验：
         1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
         2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
         3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
         4、验证app_id是否为该商户本身。
         */
        if (signVerified) {
            //商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
            //付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
            try {
                String[] split = out_trade_no.split(",");
                for (int i = 0; i < split.length; i++) {
                    //支付成功修改订单状态
                    UserOrder userOrder = new UserOrder();
                    userOrder.setOrderId(Long.parseLong(split[i]));
                    userOrder.setStatus(4);
                    userOrderService.updateUserOrderStatus(userOrder);
                }
                log.info("********************** 支付成功(支付宝同步通知) **********************");
                log.info("* 订单号: " + out_trade_no);
                log.info("* 支付宝交易号: " + trade_no);
                log.info("* 实付金额: " + total_amount);
                log.info("***************************************************************");
                return "支付成功";
            } catch (Exception e) {
                e.printStackTrace();
                return "支付失败";
            }
        }
        return "支付失败";
    }


    /**
     * 支付宝页面跳转同步通知页面
     *
     * @param request
     * @return
     * @throws UnsupportedEncodingException
     * @throws AlipayApiException
     */
    @RequestMapping(value = "/returnUrl")
    public String returnUrl(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws
            UnsupportedEncodingException, AlipayApiException {
        response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
        System.out.println("支付成功, 进入同步通知接口...");

        //获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        params = getAlipayPost(params, requestParams);

        System.out.println("params:" + params);
        //支付宝验签数据
        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.sign_type); //调用SDK验证签名

        if (signVerified) {
            //商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
            //付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
            try {
                String[] split = out_trade_no.split(",");
                for (int i = 0; i < split.length; i++) {
                    //支付成功修改订单状态
                    UserOrder userOrder = new UserOrder();
                    userOrder.setOrderId(Long.parseLong(split[i]));
                    userOrder.setStatus(4);
                    userOrderService.updateUserOrderStatus(userOrder);
                }
                log.info("********************** 支付成功(支付宝同步通知) **********************");
                log.info("* 订单号: " + out_trade_no);
                log.info("* 支付宝交易号: " + trade_no);
                log.info("* 实付金额: " + total_amount);
                log.info("***************************************************************");
                modelMap.put("status", "");
                return "normal/user_order";
            } catch (Exception e) {
                e.printStackTrace();
                return "error/payFail";
            }
        } else {
            log.info("验签失败");
            return "error/payFail";
        }
    }

}
